In [1]:
from cassandra.cqlengine import *
from cassandra.cqlengine.models import Model
from cassandra.cqlengine.management import sync_table, drop_table
from cassandra.cqlengine.connection import setup
from cassandra.cqlengine.columns import *
from uuid import uuid1, uuid4
from random import randint
setup(["localhost"], "tutorial")
Any kwargs passed to setup() will be passed to Cluster(), so it's possible to use the policies from the native driver.
In [2]:
%load_ext cql
%cql drop keyspace if exists tutorial
%cql CREATE KEYSPACE tutorial WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
%keyspace tutorial
In [3]:
class SensorData(Model):
sensor_id = UUID(primary_key=True)
created_at = TimeUUID(primary_key=True, default=uuid1)
reading = Integer()
In [4]:
drop_table(SensorData)
sync_table(SensorData)
In [16]:
sensor_id = uuid4()
for x in range(10):
reading = randint(0, 10)
data = SensorData.create(sensor_id=sensor_id, reading=reading)
print "New Reading %d: %d" % (x, reading)
In [6]:
data.reading = 1
data.save()
# or
data.update(reading=10)
Out[6]:
In [7]:
data.delete()
# or we can delete blindly if we know the id
SensorData.objects(sensor_id=sensor_id).delete()
In [8]:
class CrazyCollections(Model):
id = Integer(primary_key=True)
int_list = List(Integer)
float_map = Map(Text, Float)
text_set = Set(Text)
drop_table(CrazyCollections)
sync_table(CrazyCollections)
obj = CrazyCollections.create(id=1,
int_list=[1,2,3],
float_map={"bacon":1.1, "eggs":2.0},
text_set=set(["apple", "pie"]))
print "The map: ", obj.float_map
print "The list: ", obj.int_list
print "The set: ", obj.text_set
In [9]:
class NoJonModel(Model):
id = UUID(primary_key=True)
name = Text()
def validate(self):
super(NoJonModel, self).validate()
if self.name == "Jon":
raise ValidationError("No Jon's allowed")
sync_table(NoJonModel)
NoJonModel.create(name="Jon")
In [10]:
SensorData.ttl(60).create(sensor_id=uuid4(), reading=5)
Out[10]:
In [12]:
class User(Model):
name = Text(primary_key=True)
age = Integer()
drop_table(User)
sync_table(User)
User.create(name="Jon", age=33)
print User.get(name="Jon")
User FAIL: If the row does not exist, or multiple come back, an exception will be thrown:
In [13]:
print User.get(name="Pete")
To pull back multiple rows, we'll Querysets are chainable and lazily evaluated on access. Simply calling .objects returns a QuerySet which has not been evaluated.
In [17]:
SensorData.objects(sensor_id=sensor_id)
Out[17]:
By iterating over the queryset we tell the query to execute:
In [15]:
for s in SensorData.objects(sensor_id=sensor_id).limit(2):
print s, s.reading
In [18]:
class Automobile(Model):
manufacturer = Text(primary_key=True)
year = Integer(primary_key=True)
model = Text(primary_key=True)
price = Decimal()
drop_table(Automobile)
sync_table(Automobile)
Automobile.create(manufacturer="Tesla", year=2013, model="Model S", price=70000)
Automobile.create(manufacturer="Tesla", year=2014, model="Model S", price=70000)
Automobile.create(manufacturer="Tesla", year=2015, model="Model S", price=70000)
Automobile.create(manufacturer="Tesla", year=2015, model="Model X", price=50000)
list(Automobile.objects(manufacturer="Tesla", year__gt=2014))
Out[18]:
In [ ]:
# alternate syntax
list(Automobile.objects(manufacturer="Tesla").filter(Automobile.year > 2014))
In [ ]:
class OrderedTable(Model):
id = Integer(primary_key=True)
ck = Integer(primary_key=True)
val = Integer()
drop_table(OrderedTable)
sync_table(OrderedTable)
for x in range(10):
OrderedTable.create(id=1, ck=x, val=x)
print "Forward: ", [x.ck for x in OrderedTable.objects(id=1)]
print "Reversed: ", [x.ck for x in OrderedTable.objects(id=1).order_by("-ck")]
In [ ]:
list(SensorData.objects().values_list('reading', 'created_at'))
Or just a list:
In [ ]:
list(SensorData.objects().values_list('reading', flat=True))
Batches are useful in situations where you need to know that all or none of the queries get executed. By default a batch is logged, meaning even if the mutation is only partially applied, eventually the whole thing will be. This is useful when 2 tables absolutely have to be updated (such as some data and an index)
In [ ]:
from cqlengine import BatchQuery
drop_table(SensorData)
sync_table(SensorData)
with BatchQuery() as b:
for x in range(10):
reading = randint(0, 10)
SensorData.batch(b).create(sensor_id=sensor_id, reading=reading)
In [ ]:
jon = User.if_not_exists().create(name="Jon", age=100)
In [ ]:
jon.iff(age=100).update(age=101)
In [ ]:
from cassandra.cqlengine import LeveledCompactionStrategy
class User(Model):
__compaction__ = LeveledCompactionStrategy
__gc_grace_seconds__ = 10000
__read_repair_chance__ = 0.5
user_id = UUID(primary_key=True)
name = Text()
drop_table(User)
sync_table(User)
In [ ]:
from datetime import datetime
class BaseTweet(Model):
__abstract__ = True
tweet_id = Integer(primary_key=True)
text = Text()
created_at = DateTime(default=datetime.now)
class StandardTweet(BaseTweet):
pass
class PromotedTweet(BaseTweet):
budget = Decimal()
sync_table(StandardTweet)
sync_table(PromotedTweet)
In [ ]:
%tables
Each of the different tweet types lives in it's own table but the structure is inherited from the base table.
The above example will create 2 tables, one for each type of tweet. But what if we want to do a single query that gets both results? There's no UNION built into CQL. For this, we use table polymorphism.
In [ ]:
from datetime import datetime
class Tweet(Model):
__table_name__ = 'tweet'
__discriminator_column__ = 'ad_type'
tweet_id = Integer(primary_key=True)
text = Text()
created_at = DateTime(default=datetime.now)
ad_type = Text(index=True)
class StandardTweet(Tweet):
__discriminator_value__ = 'standard'
class PromotedTweet(Tweet):
__discriminator_value__ = 'promoted'
budget = Decimal()
drop_table(Tweet)
sync_table(StandardTweet)
sync_table(PromotedTweet)
In [ ]:
%tables
In [ ]:
import pprint
pp = pprint.PrettyPrinter(indent=4)
In [ ]:
for x in range(2):
StandardTweet.create(tweet_id=x, text="standard")
for x in range(2, 4):
PromotedTweet.create(tweet_id=x, text="promoted")
Tweet.objects()[:]
In [ ]:
print "standard tweets: "
pp.pprint(StandardTweet.objects()[:])
print "promoted tweets: "
pp.pprint(PromotedTweet.objects()[:])
In [ ]: